#include "Server.hpp"

// ==========================================================================
// implementation
// ==========================================================================

// --------------------------------------------------------------------------
// the application class
// --------------------------------------------------------------------------

bool MyApp::OnInit()
{
    // Create the main application window
    MyFrame *frame = new MyFrame();

    // Show it and tell the application that it's our main window
    frame->Show(true);
    SetTopWindow(frame);

    // Success
    return true;
}

// --------------------------------------------------------------------------
// main frame
// --------------------------------------------------------------------------

// frame constructor

MyFrame::MyFrame() : wxFrame(NULL, wxID_ANY, _("wxSocket Event Demo: Server"),
                             wxDefaultPosition, wxSize(300, 200))
{
    m_server = NULL;
	nbFailure=0;
    
    // Give the frame an icon
    SetIcon(wxICON(mondrian));

    // Make menus
    m_menuFile = new wxMenu();
    m_menuFile->Append(SERVER_START, _("&Start"), _("Start the server"));
    m_menuFile->AppendSeparator();
    m_menuFile->Append(SERVER_QUIT, _("E&xit\tAlt-X"), _("Quit server"));

    // Append menus to the menubar
    m_menuBar = new wxMenuBar();
    m_menuBar->Append(m_menuFile, _("&File"));
    SetMenuBar(m_menuBar);

    // Make a textctrl for logging
    m_text  = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
                             wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);

    m_text->AppendText(_("Welcome to the Socket Event Demo: Server\nYou need to Start the server!\n"));
}

MyFrame::~MyFrame()
{
    // No delayed deletion here, as the frame is dying anyway
    delete m_server;
}

// event handlers

void MyFrame::OnServerStart(wxCommandEvent& WXUNUSED(event))
{
    // Create the address - defaults to localhost
    wxIPV4address addr;
    addr.Service(3000);

    // Create the socket, we maintain a class pointer so we can shut it down
    m_server = new wxSocketServer(addr);

    // We use Ok() here to see if the server is really listening
    if (! m_server->Ok())
    {
        return;
    }

    m_text->AppendText(_("\nSocket server listening.\n"));

    // Setup the event handler and subscribe to connection events
    m_server->SetEventHandler(*this, SERVER_ID);
    m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
    m_server->Notify(true);
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    // true is to force the frame to close
    Close(true);
}

void MyFrame::OnServerEvent(wxSocketEvent& WXUNUSED(event))
{
    // Accept the new connection and get the socket pointer
    wxSocketBase* sock = m_server->Accept(false);

    // Tell the new socket how and where to process its events
    sock->SetEventHandler(*this, SOCKET_ID);
    sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
    sock->Notify(true);

    m_text->AppendText(_("\nAccepted incoming connection.\n"));

	//choose word
	m_word = new wxString(wxT("AZERTY"));
	m_wordToShow = new wxString(wxT("A____Y"));
    
	//envoi mot a trouver au client
	wxString message = wxString(wxEmptyString);

	message += wxT("0");
	message += wxT(":");
    message += *m_wordToShow;
	message += wxT(":");
	message += wxT("0");

	char buf[100];
    strcpy(buf, (const char*)message.mb_str(wxConvUTF8));
	sock->Write(buf,sizeof(buf));
}

void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
    wxSocketBase *sock = event.GetSocket();

    // Process the event
    switch(event.GetSocketEvent())
    {
        case wxSOCKET_INPUT:
        { 
            char buf[10];

            // Read the data
            sock->Read(buf, sizeof(buf));

            m_text->AppendText(wxString(_("Received from client: ")) + wxString(buf, wxConvUTF8, 1) + _("\n"));

			bool found=AnalyzeGuess(wxString(buf, wxConvUTF8, 1));

			if(!found)
			{
				nbFailure++;
			}

            // Write it back
            char bufsend[100];
			
			wxString message = wxString(wxEmptyString);
			wxString sNbFailure = wxString() << nbFailure;


			message += sNbFailure;
			message += wxT(":");
			message += *m_wordToShow;
			message += wxT(":");
			//determine victory or defeat
			if(m_word->CmpNoCase(*m_wordToShow)==0)
			{
				//win
				message += wxT("1");
			}
			else if(nbFailure >= 11)
			{
				//loose
				message += wxT("2");
			}
			else
			{
				message += wxT("0");
			}

			strcpy(bufsend, (const char*)message.mb_str(wxConvUTF8));
			sock->Write(bufsend,sizeof(bufsend));

            m_text->AppendText(_("Wrote string back to client.\n"));

			//if player looses, eject him
			if(nbFailure == 11)
			{
				sock->Destroy();
				nbFailure=0;
			}

            break;
        }
        case wxSOCKET_LOST:
        {
            sock->Destroy();
			nbFailure=0;
            break;
        }
    }
}

bool MyFrame::AnalyzeGuess(wxString& guess)
{
	int i=0;
	bool found=false;
	while(i<m_word->Len())
	{
		if( m_word->GetChar(i) == guess.GetChar(0))
		{
			found=true;
			m_wordToShow->SetChar(i,guess.GetChar(0));
		}
		i++;
	}
	return found;
}
